﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Quartz;
using Quartz.Impl;
using System.Threading;
using System.Data.Linq;
using Study.App_Code;
using FlyLib.Entities;

namespace 作业调度
{
    class Program
    {
        static void Main(string[] args)
        {
            //Console.WriteLine("开始调用简单Demo");
            //SimpleDemo();

            //Console.WriteLine("开始调用复杂Demo");
            //ComplexDemo();
            Console.WriteLine("计划任务运行中...");

            TB_TaskPlan p1 = new TB_TaskPlan();
            using (DataContext dc = new DataContext(DBAccess._connectionString))
            {
                p1 = dc.GetTable<TB_TaskPlan>().FirstOrDefault();
                
            }

            TaskPlan.AddScheduleJob(p1);
            TaskPlan.RunScheduleJob("测试任务2", "分组2");

            Console.ReadKey();
        }

        //简单Demo，指定时间间隔执行作业
        public static void SimpleDemo()
        {
            DateTime start=DateTime.Now.AddSeconds(1);//作业开始时间
            DateTime end = DateTime.Now.AddHours(2);//作业结束时间
            int job_interval = 2;//作业间隔时间 单位：秒
            int jobCount = 5;//作业重复次数，如果在执行完指定重复次数后还未到达作业结束时间，依然会结束作业

            //1.首先创建一个作业调度池
            ISchedulerFactory schedf = new StdSchedulerFactory();
            IScheduler sched = schedf.GetScheduler();
            //2.创建出来一个具体的作业
            IJobDetail job = JobBuilder.Create<JobDemo>().Build();

            //设置作业开始/结束时间
            DateTimeOffset startTime = DateBuilder.NextGivenSecondDate(start, 2);
            DateTimeOffset endTime = DateBuilder.NextGivenSecondDate(DateTime.Now.AddHours(2), 3);

            //3.创建并配置一个触发器
            ISimpleTrigger trigger = (ISimpleTrigger)TriggerBuilder.Create()
                .StartAt(startTime)
                .EndAt(endTime)
                .WithSimpleSchedule(x => x.WithIntervalInSeconds(job_interval)
                .WithRepeatCount(jobCount))
                .Build();

            //4.加入作业调度池中
            sched.ScheduleJob(job, trigger);

            //5.开始运行
            sched.Start();
            
        }

        //复杂Demo，在指定时间维度执行作业(某个时间点，如每天14:00-15:00的每分钟,...)
        public static void ComplexDemo()
        {
            //首先创建一个作业调度池
            ISchedulerFactory schedf = new StdSchedulerFactory();
            IScheduler sched = schedf.GetScheduler();
            //创建出来一个具体的作业
            IJobDetail job = JobBuilder.Create<JobDemo2>()
                //.WithIdentity("name","group")
                .Build();
            //NextGivenSecondDate：如果第一个参数为null则表名当前时间往后推迟2秒的时间点。
            DateTimeOffset startTime = DateBuilder.NextGivenSecondDate(DateTime.Now.AddSeconds(1), 2);
            DateTimeOffset endTime = DateBuilder.NextGivenSecondDate(DateTime.Now.AddYears(2), 3);

            //创建并配置一个触发器
            //cron表达式是有7个域的，依次分别是：秒分时日月周年，其中年是可选类型，也就是说他如果在不设定年分的情况下是每年
            // * 表示所有值
            // ? 日期域和星期域中使用。它被用来指定“非明确的值”
            // - 指定一个范围
            // ，指定几个可选值
            // / 指定增量。如：“0/15”在秒域意思是没分钟的0，15，30和45秒

            /* L 表示day-of-month和day-of-week域，但在两个字段中的意思不同，
             例如day-of-month域中表示一个月的最后一天。如果在day-of-week域表示‘7’或者‘SAT’，
             如果在day-of-week域中前面加上数字，它表示一个月的最后几天，例如‘6L’就表示一个月的最后一个星期五
             */

            /*
               W 只允许日期域出现。这个字符用于指定日期的最近工作日。
             * 例如：如果你在日期域中写 “15W”，表示：这个月15号最近的工作日。所以，
             * 如果15号是周六，则任务会在14号触发。
             * 如果15好是周日，则任务会在周一也就是16号触发。
             * 如果是在日期域填写“1W”即使1号是周六，那么任务也只会在下周一，也就是3号触发，
             * “W”字符指定的最近工作日是不能够跨月份的。
             * 字符“W”只能配合一个单独的数值使用，不能够是一个数字段，如：1-15W是错误的
             */

            // LW 在日期域中联合使用，LW表示这个月最后一周的工作日

            /* # 只允许在星期域中出现。这个字符用于指定本月的某某天。
               例如：“6#3”表示本月第三周的星期五（6表示星期五，3表示第三周）
            */
            ICronTrigger trigger = (ICronTrigger)TriggerBuilder.Create()
                .StartAt(startTime)
                .EndAt(endTime)
                .WithCronSchedule("1,10,14,30,31 * * * * ? ")
                //.WithIdentity("name","group")
                .Build();
            //加入作业调度池中
            sched.ScheduleJob(job, trigger);
            //开始运行
            sched.Start();
            
            //挂起10秒
            //Thread.Sleep(TimeSpan.FromSeconds(10));
            //10秒后关闭作业调度，将不在执行
            //sched.Shutdown();
            Console.ReadKey();
        }

        public class JobDemo : IJob
        {
            /// <summary>
            /// 这里是作业调度每次定时执行方法
            /// </summary>
            /// <param name="context"></param>
            public void Execute(IJobExecutionContext context)
            {
                Console.WriteLine("每隔2秒执行一次");
            }
        }

        public class JobDemo2 : IJob
        {
            /// <summary>
            /// 按照指定时间维度执行方法
            /// </summary>
            /// <param name="context"></param>
            public void Execute(IJobExecutionContext context)
            {
                Console.WriteLine("按照指定时间维度执行作业，执行时间:"+DateTime.Now);
            }
        }

        
    }
}
